/*
 * @Author: wangzy
 * @Date: 2022-06-20 09:55:39
 * @LastEditors: wangzy
 * @LastEditTime: 2022-06-20 15:58:53
 * @Description: 抽象工厂
 */
/**
 * 开放封闭原则:  对拓展开放，对修改封闭。说得更准确点，软件实体（类、模块、函数）可以扩展，但是不可修改
 **/
/**
 * 大家知道一部智能手机的基本组成是操作系统（Operating System，我们下面缩写作 OS）和硬件（HardWare）组成。
 * 所以说如果我要开一个山寨手机工厂，那我这个工厂里必须是既准备好了操作系统，也准备好了硬件，才能实现手机的量产。
 * 考虑到操作系统和硬件这两样东西背后也存在不同的厂商，而我现在并不知道我下一个生产线到底具体想生产一台什么样的手机，
 * 我只知道手机必须有这两部分组成，所以我先来一个抽象类来约定住这台手机的基本组成
 **/

//  抽象工厂 仅仅是用来定规矩的
class MobilePhoneFactory {
  // 提供操作系统的接口
  createOS() {
    throw new Error('抽象工厂方法不允许直接调用，你需要将我重写！')
  }
  // 提供硬件的接口
  createHardWare() {
    throw new Error('抽象工厂方法不允许直接调用，你需要将我重写！')
  }
}
// 抽象工厂不干活，具体工厂FakeStarFactory继承抽象工厂的规矩来干活
class FakeStarFactory extends MobilePhoneFactory {
  createOS() {
    // 重写 抽象工厂中的createOS 并返回一个操作系统类型
    return new AndroidOS()
    // console.log('重写了createOS')
  }
  createHardWare() {
    // 重写 抽象工厂中的createHardWare 并返回一个硬件
    return new QualcommHardWare()
    // console.log('重写了createHardWare')
  }
}
// let fsf = new FakeStarFactory()
// fsf.createOS()
// fsf.createHardWare()

/**
 * 这里在提供安卓系统的时候，调用了两个构造函数：AndroidOS 和 QualcommHardWare
 * 它们分别用于生产具体的操作系统和硬件实例。像这种被拿来用于 new 出具体对象的类，叫做具体产品类
 * 具体产品类往往不会孤立存在，不同的具体产品类往往有着共同的功能，比如安卓系统类和苹果系统类，它们都是操作系统
 * 都有着可以 操控手机硬件系统 这样一个最基本的功能。因此我们可以用一个抽象产品类来声明这一类产品应该具有的基本功能
 **/

// 定义操作系统这类产品的抽象产品类
class OS {
  controlHardWare() {
    throw new Error('抽象产品方法不允许直接调用，你需要将我重写！')
  }
}
// 定义具体操作系统的具体产品类
class AndroidOS extends OS {
  controlHardWare() {
    console.log('我会用安卓的方式操作硬件')
  }
}
class AppleOS extends OS {
  controlHardWare() {
    console.log('我会用苹果的方式操作硬件')
  }
}
// 定义手机硬件这类产品的抽象产品类
class HardWare {
  // 手机硬件的共性方法，这里提取了“根据命令运转”这个共性
  operateByOrder() {
    throw new Error('抽象产品方法不允许直接调用，你需要将我重写！')
  }
}
//定义具体硬件的具体产品类
class QualcommHardWare extends HardWare {
  operateByOrder() {
    console.log('我会用高通的方式去运转')
  }
}

class MiWare extends HardWare {
  operateByOrder() {
    console.log('我会用小米的方式去运转')
  }
}
//好了，如此一来，当我们需要生产一台FakeStar手机时，我们只需要这样做：
// 这是我的手机
const myPhone = new FakeStarFactory()
// 让它拥有操作系统
const myOS = myPhone.createOS()
// 让它拥有硬件
const myHardWare = myPhone.createHardWare()
// 启动操作系统(输出‘我会用安卓的方式去操作硬件’)
myOS.controlHardWare()
// 唤醒硬件(输出‘我会用高通的方式去运转’)
myHardWare.operateByOrder()
